package Railroad.Communication;

import Railroad.Communication.Codes.CommunicationCodes;
import Railroad.Components.Switch;
import java.util.List;

public class MessageBuilder {
    public CommData buildBase(byte code) {
        //System.out.println("> " + code);
        CommData data = new CommData();
        data.put(code);
        return data;
    }
    
    public CommData buildPing() {
        return buildBase(CommunicationCodes.Out.Ping);
    }
    
    public CommData buildClearanceRequest(byte[] segments) {
        return buildBase(CommunicationCodes.Out.ClearanceStatusRequest)
                .put(maskFromArray(segments));
    }
    
    public CommData buildSetSwitchStatusRequest(List<Switch> switches) {
        int size = switches.size();
        byte[] switchList = new byte[size];
        byte[] statusList = new byte[size];
        for (int i = 0; i < size; i++) {
            Switch sw = switches.get(i);
            switchList[i] = (byte) sw.getIdInDevice();
            statusList[i] = (byte) sw.getRequestedStatus().get();
        }
        return buildSetSwitchStatusRequest(switchList, statusList);
    }
    
    public CommData buildSetSwitchStatusRequest(byte[] switches, byte[] statuses) {
        return buildBase(CommunicationCodes.Out.SetSwitchStatus)
                .put((byte)0)     // address
                .put(createSwitchStatusMask(switches, statuses));
    }
    
    public CommData buildGetSwitchStatusRequest(byte[] switches) {
        return buildBase(CommunicationCodes.Out.GetSwitchStatus)
                 .put((byte)0);    // address
    }
    
    private byte createSwitchStatusMask(byte[] switches, byte[] statuses) {
        byte mask = 0;
        for (int i = 0; i < switches.length; i++) {
            mask |= (statuses[i]) << (2 * switches[i]);
        }
        return mask;
    }
    
    private byte maskFromArray(byte[] array) {
        byte mask = 0;
        for (byte val : array)
            mask |= (1 << val);
        return mask;
    }
}
